package order;

import controller.SessionAttribute;
import entity.CommodityLocal;
import entity.CommodityLocalHome;
import entity.OrdersLocal;
import entity.OrdersLocalHome;
import helper.SimpleJSONObject;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import javax.ejb.FinderException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import transfer.Commodity;
import transfer.OrderState;

/**
 *
 * @author Oleh
 */
public class Cart extends HttpServlet {

    public static final String actionParameter = "action";
    public static final String idParameter = "id";
    public static final String quantityParameter = "quantity";
    public static final String addAction = "add";
    public static final String removeAction = "remove";
    public static final String countAction = "count";
    public static final String error = "error";
    public static final String ok = "ok";
    public static final String answer = "answer";
    public static final String totalCost = "totalCost";
    public static final String commoditiesCount = "commoditiesCount";
    public static final int MAX_QUANTITY = 10000;
    public static final String TOO_MUCH = "tooMuch";

    /**
     * Processes requests for both HTTP
     * <code>GET</code> and
     * <code>POST</code> methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        SimpleJSONObject json = new SimpleJSONObject();
        String action = request.getParameter(actionParameter);
        Integer idCommodity = Integer.valueOf(request.getParameter(idParameter));
        HttpSession session = request.getSession();
        prepareSession(session);
        transfer.Order cart = (transfer.Order) session.getAttribute(SessionAttribute.CART);
        Commodity commodity = null;
        try {
            Context c = new InitialContext();
            CommodityLocalHome commodityHome = (CommodityLocalHome) c.lookup("java:comp/env/Commodity");
            CommodityLocal commodityLocal = commodityHome.findByPrimaryKey(idCommodity);
            commodity = commodityLocal.getCommodity();
        } catch (NamingException ex) {
            ex.printStackTrace();
        } catch (FinderException ex) {
            ex.printStackTrace();
        }
        if (action.equals(addAction)) {
            HashMap map = cart.getCommodities();
            Integer quantity = (Integer) map.get(commodity);
            if (quantity != null) {
                if (quantity.intValue() < MAX_QUANTITY) {
                    quantity = new Integer(quantity.intValue() + 1);
                } else {
                    json.addProperty(TOO_MUCH, commodity.getNameCommodity());
                }
            } else {
                quantity = new Integer(1);
            }
            map.put(commodity, quantity);
            cart.setCommodities(map);
            cart.setCostCommodities(calculateTotalCost(cart));
        } else if (action.equals(removeAction)) {
            HashMap map = cart.getCommodities();
            map.remove(commodity);
            cart.setCommodities(map);
            cart.setCostCommodities(calculateTotalCost(cart));
        } else if (action.equals(countAction)) {
            Integer quantity = Integer.valueOf(request.getParameter(quantityParameter));
            HashMap map = cart.getCommodities();
            map.put(commodity, quantity);
            cart.setCommodities(map);
            cart.setCostCommodities(calculateTotalCost(cart));
        }
        session.setAttribute(SessionAttribute.CART, cart);
        Boolean signIn = (Boolean) session.getAttribute(SessionAttribute.SIGN_IN);
        if (signIn != null && signIn.equals(Boolean.TRUE)) {
            try {
                InitialContext context = new InitialContext();
                OrdersLocalHome homeOrder = (OrdersLocalHome) context.lookup("java:comp/env/Orders");
                OrdersLocal localOrder = (OrdersLocal) homeOrder.findByPrimaryKey(cart.getIdOrder());
                localOrder.setOrder(cart);
            } catch (NamingException ex) {
                ex.printStackTrace();
            } catch (FinderException ex) {
                ex.printStackTrace();
            }

        }

        json.addProperty(answer, ok);
        json.addProperty(totalCost, "" + cart.getCostCommodities());
        json.addProperty(commoditiesCount, "" + cart.getCommodities().size());
        response.setContentType("application/json;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println(json);
        out.close();
    }

    private void prepareSession(HttpSession session) {
        if (session.getAttribute(SessionAttribute.CART) == null) {
            transfer.Order cart = new transfer.Order();
            cart.setOrderState(OrderState.ENTERING);
            cart.setTotalCost(new Double(0));
            cart.setIsSubscribed(Boolean.FALSE);
            cart.setCommodities(new HashMap());
            session.setAttribute(SessionAttribute.CART, cart);
        }
    }

    private Double calculateTotalCost(transfer.Order order) {
        double sum = 0;
        HashMap map = order.getCommodities();
        Set keySet = map.keySet();
        Iterator iterator = keySet.iterator();
        while (iterator.hasNext()) {
            Commodity commodity = (Commodity) iterator.next();
            int quantity = ((Integer) map.get(commodity)).intValue();
            sum += commodity.getPrice().doubleValue() * quantity;
        }
        return new Double(sum);
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP
     * <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}
